package top.yueyazhui.data_scope.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import top.yueyazhui.data_scope.annotation.DataScope;
import top.yueyazhui.data_scope.entity.BaseEntity;
import top.yueyazhui.data_scope.entity.Role;
import top.yueyazhui.data_scope.entity.User;
import top.yueyazhui.data_scope.util.SecurityUtil;

import java.util.List;

@Aspect
@Component
public class DataScopeAspect {

    // 数据权限（1：全部数据权限 2：自定数据权限 3：本部门数据权限 4：本部门及以下数据权限 5: 只能查看自己的数据）
    public static final String DATA_SCOPE_ALL = "1";
    public static final String DATA_SCOPE_CUSTOM = "2";
    public static final String DATA_SCOPE_DEPT = "3";
    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
    public static final String DATA_SCOPE_SELF = "5";
    // key
    public static final String DATA_SCOPE = "data_scope";

    @Before("@annotation(dataScope)")
    public void before(JoinPoint jp, DataScope dataScope) {
        clearDataScope(jp);
        // 获取当前登录用户的用户信息
        User user = SecurityUtil.getLoginUser();
        if (user.getUserId() == 1L) {
            // 超级管理员，不用进行权限过滤
            return;
        }
        StringBuilder sql = new StringBuilder();
        List<Role> roles = user.getRoles();
        // SELECT * FROM sys_dept d WHERE d.del_flag='0' AND (xxx OR xxx OR xxx)
        // d.dept_id IN (SELECT rd.dept_id FROM sys_role_dept rd WHERE rd.role_id = 2) 代表一个 xxx
        for (Role role : roles) {
            String ds = role.getDataScope();
            if (DATA_SCOPE_ALL.equals(ds)) {
                // 全部数据权限
                return;
            } else if (DATA_SCOPE_CUSTOM.equals(ds)) {
                // 自定数据权限：根据角色ID查找部门ID
                sql.append(String.format(" OR %s.dept_id IN (SELECT rd.dept_id FROM sys_role_dept rd WHERE rd.role_id = %d)", dataScope.deptAlias(), role.getRoleId()));
            } else if (DATA_SCOPE_DEPT.equals(ds)) {
                // 本部门数据权限
                sql.append(String.format(" OR %s.dept_id = %d", dataScope.deptAlias(), user.getDeptId()));
            } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(ds)) {
                // 本部门及以下数据权限
                sql.append(String.format(" OR %s.dept_id IN (SELECT dept_id FROM sys_dept WHERE dept_id = %d OR FIND_IN_SET(%d, ancestors))", dataScope.deptAlias(), user.getDeptId(), user.getDeptId()));
            } else if (DATA_SCOPE_SELF.equals(ds)) {
                // 只能查看自己的数据
                String ua = dataScope.userAlias();
                if ("".equals(ua)) {
                    // 数据权限仅限于本人
                    sql.append(" OR 1=0");
                } else {
                    sql.append(String.format(" OR %s.user_id = %d", dataScope.userAlias(), user.getUserId()));
                }
            }
        }
        //  AND (xxx OR xxx OR xxx)
        Object arg = jp.getArgs()[0];
        if (arg != null && arg instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) arg;
            baseEntity.getParams().put(DATA_SCOPE, " AND (" + sql.substring(4) + ")");
        }
    }

    /**
     * 如果 params 中已经有参数了，则删除掉，防止 SQL 注入
     * @param jp
     */
    private void clearDataScope(JoinPoint jp) {
        Object arg = jp.getArgs()[0];
        if (arg != null && arg instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) arg;
            baseEntity.getParams().put(DATA_SCOPE, "");
        }
    }
}
